Skip to content

chore: add support for react-native@0.87.0-rc.3 - #4375

Merged
t0maboro merged 26 commits into
mainfrom
@t0maboro/rn-087
Jul 31, 2026
Merged

t0maboro merged 26 commits into
mainfrom
@t0maboro/rn-087

Conversation

@t0maboro

@t0maboro t0maboro commented Jul 21, 2026 •

Copy link
Copy Markdown
Member

Description

Upgrade based on the RN upgrade helper: https://react-native-community.github.io/upgrade-helper/?from=0.86.0&to=0.87.0-rc.3

Closes: https://github.com/software-mansion/react-native-screens-labs/issues/1666

Changes

Baseline

TypeScript - RN 0.87 strict TS API + TS 6 support

  • In RN 0.87's generated types, View is a function component, so React.Ref<View> / useRef<View> no longer describe a host instance. All ref sites (e.g., Screen, ScreenStackItem, ScreenStackHeaderConfig) now use the public ViewInstance type.
  • RN 0.87's real types live under the types_generated/ (treated as non-public) path, so any inferred exported type referencing them fails .d.ts emit during npm pack (bob build). Fixes:
  • Set rootDir: "./src" in tsconfig.build.json
  • moduleResolution: "bundler", dropped baseUrl.** bundler resolution is required to resolve RN 0.87's exports-based type entry points; baseUrl is deprecated in TS 6 and the paths mappings work relative to the config without it. For more context, see: 6.0 Migration Guide microsoft/TypeScript#62508
  • Restored the removed TextInputFocusEventData. RN changed the exported type to TextInputFocusEvent (now the full NativeSyntheticEvent). A local backward-compat interface is introduced.

SearchBar

  • Migrated from forwardRef to React 19 ref-as-prop
  • Retyped the internal ref against the native host instance (React.ComponentRef<typeof SearchBarNativeComponent>) instead of the previous double-casted NativeSearchBar wrapper.

iOS

  • Added missing _props default initializers to Fabric component views (e.g., RNSScreenContentWrapper). RCTViewComponentView's updateProps:oldProps: asserts in debug builds that every subclass initializes _props with its own concrete default props in its initializer, starting from 0.87.

Android

  • AGP 9 has built-in Kotlin support.
  • AGP 9 compiles Kotlin itself by default, and additionally applying kotlin-android plugin fails the build - so the plugin is now applied only when built-in Kotlin is inactive (AGP < 9, or the consumer opted out via android.builtInKotlin=false).
  • Registered src/fabric/java in the Kotlin source set so the Fabric sources compile under built-in Kotlin.

Before & after - visual documentation

N/A

Test plan

  • yarn check-types - passed
  • npm pack - passed
  • codegen was verified
  • FabricExample - built and run on iOS and Android.
  • Checked the compatibility with the lowest supported RN version (0.84)

Action items yet to be covered:

  • test it with SwiftPM
  • full testing coverage of the most important components on (0.84, 0.87) x (Android, iOS) x (Debug, Release) combos
  • more FabricExample testing - both Debug and Release
  • consider adding some commit-level check for detecting issues related to non-public types and TS inference.

Checklist

  • Included code example that can be used to test this change.
  • For visual changes, included screenshots / GIFs / recordings documenting the change.
  • For API changes, updated relevant public types.
  • Ensured that CI passes

Comment thread src/components/Screen.tsx Outdated
Comment thread src/legacy/types.ts Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates react-native-screens to build and type-check against react-native@0.87.0-rc.1, including related dependency/tooling bumps and several type-level adjustments required by upstream React Native and Android Gradle Plugin changes.

Changes:

  • Update JS/TS types and component implementations to align with RN 0.87 type exports and stricter TS settings (e.g., ViewInstance, removed RN exports, exactOptionalPropertyTypes).
  • Adjust Android Gradle integration for AGP 9 built-in Kotlin behavior and update example Android tooling (Gradle, SDK, Kotlin).
  • Initialize default Fabric _props in several iOS component views to match RN 0.87 expectations.

Reviewed changes

Copilot reviewed 28 out of 33 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tsconfig.json Switch TS module resolution to bundler and adjust path mappings for the library.
src/types.tsx Update public types for RN 0.87 (e.g., ViewInstance) and add local TextInputFocusEventData compatibility type.
src/private/hooks/useRenderDebugInfo.tsx Replace removed/renamed RN types (ReactNativeElement → HostInstance).
src/gesture-handler/fabricUtils.ts Update ref/instance typing to RN 0.87’s ViewInstance.
src/fabric/SearchBarNativeComponent.ts Update native commands typing to newer React ref helper types.
src/components/tabs/host/TabsHost.android.tsx Avoid passing { direction: undefined } in styles under stricter typing.
src/components/SearchBar.tsx Refactor SearchBar ref/commands wiring to match RN 0.87 typing changes.
src/components/ScreenStackItem.tsx Update forwarded ref typing and tighten optional style handling.
src/components/ScreenStackHeaderConfig.tsx Adjust non-iOS alignItems to explicit Yoga default (stretch).
src/components/Screen.web.tsx Attempt to pass ref through to inner web <View/>.
src/components/Screen.tsx Update ref typing and add cast workaround for zIndex: undefined under exactOptionalPropertyTypes.
src/components/gamma/stack/host/StackHost.types.ts Update host ref type from ReactNativeElement to HostInstance.
src/components/gamma/stack/host/StackHost.tsx Normalize ref passed to native component (undefined → null).
src/components/gamma/stack/header/ios/StackHeaderItem.ios.tsx Guard Image.resolveAssetSource returning falsy.
package.json Bump RN toolchain/dev deps to 0.87.0-rc.1 and TypeScript to ^6.0.3.
ios/tabs/bottom-accessory/RNSTabsBottomAccessoryContentComponentView.mm Set default Fabric _props in initializer.
ios/tabs/bottom-accessory/RNSTabsBottomAccessoryComponentView.mm Set default Fabric _props in initializer.
ios/RNSScreenFooter.mm Set default Fabric _props in initializer.
ios/RNSScreenContentWrapper.mm Add initWithFrame to set default Fabric _props.
ios/gamma/stack/host/RNSStackHostComponentView.mm Set default Fabric _props in initializer.
ios/gamma/modals/form-sheet/RNSFormSheetContentWrapperComponentView.mm Add initWithFrame to set default Fabric _props.
FabricExample/yarn.lock Update example lockfile for RN 0.87 toolchain and dependency graph changes.
FabricExample/tsconfig.json Update example TS types list.
FabricExample/package.json Bump example app RN + toolchain deps to 0.87.0-rc.1 and TS ^6.0.3.
FabricExample/ios/Podfile.lock Update CocoaPods lockfile for RN 0.87.0-rc.1 pods/layout.
FabricExample/android/gradlew Update gradlew template link reference.
FabricExample/android/gradle/wrapper/gradle-wrapper.properties Bump Gradle distribution to 9.4.1.
FabricExample/android/gradle.properties Add AGP 9 opt-outs for built-in Kotlin and new DSL.
FabricExample/android/build.gradle Bump compile/build tools and Kotlin versions.
FabricExample/android/app/build.gradle Switch to proguard-android-optimize.txt.
android/build.gradle Conditionally apply Kotlin plugin based on AGP 9 built-in Kotlin; add kotlin source dir configuration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/legacy/components/SearchBar.tsx
Comment thread src/legacy/components/SearchBar.tsx
Comment thread src/components/Screen.web.tsx Outdated
Comment thread FabricExample/tsconfig.json
@t0maboro
t0maboro marked this pull request as ready for review July 28, 2026 14:40
@t0maboro t0maboro changed the title chore: add support for react-native@0.87.0-rc.1 chore: add support for react-native@0.87.0-rc.3 Jul 28, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 58 out of 63 changed files in this pull request and generated no new comments.

Comments suppressed due to low confidence (2)

src/legacy/components/SearchBar.tsx:28

  • props.ref is now being consumed directly (React 19 ref-as-prop), but SearchBarProps['ref'] is typed as React.RefObject<...> only. That prevents callback refs ((instance) => {}) from type-checking, even though useImperativeHandle supports them. Consider widening the public prop type to React.Ref<SearchBarCommands | null> (or equivalent) so both object and callback refs work.
    src/legacy/components/helpers/prepareHeaderBarButtonItems.ts:66
  • prepareHeaderBarButtonItems is exported but currently has an inferred return type and optional-chains an argument that’s already typed as a non-null array. Adding an explicit return type and using .map directly helps keep the emitted .d.ts surface stable and avoids leaking implementation-only types into declarations.

@t0maboro t0maboro added the action:backport-to-v4 Add this label to any issue or PR that should be backported to the v4 line of the library. label Jul 28, 2026

@kligarski kligarski left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good but I left a few minor comments that we should look at before proceeding.

Comment thread tsconfig.json

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we also need to apply the same update to library-level gradle-wrapper.properties?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided not to bump because it hasn't been bumped in many previous RN upgrades; tbh, not sure whether we should consider bumping that, but I think this might be another topic - the Kotlin version for the library is still set to 1.8.0 while on the example app's side it is 2+. I'd leave it as-is for now.

Comment thread android/build.gradle
Comment thread ios/stack/host/RNSStackHostComponentView.mm Outdated
Comment thread src/legacy/types.ts Outdated
Comment thread src/fabric/split/SplitHostNativeComponent.ts Outdated
Comment thread src/legacy/components/ScreenStackHeaderConfig.tsx
@t0maboro
t0maboro requested a review from kligarski July 30, 2026 13:15

@kligarski kligarski left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. I haven't checked the runtime after the changes.

@t0maboro
t0maboro merged commit 7708a4a into main Jul 31, 2026
8 of 9 checks passed
@t0maboro
t0maboro deleted the @t0maboro/rn-087 branch July 31, 2026 08:13
@t0maboro t0maboro mentioned this pull request Jul 31, 2026
2 tasks
t0maboro added a commit that referenced this pull request Aug 5, 2026
Upgrade based on the RN upgrade helper:

https://react-native-community.github.io/upgrade-helper/?from=0.86.0&to=0.87.0-rc.3

Closes:

software-mansion/react-native-screens-labs#1666

- Bumped RN.packages to `0.87.0-rc.3` and TypeScript to TS6
- Bumped AGP on Android to 9
- Bumped `react-native-safe-area-context` to 5.8.0 -

https://github.com/AppAndFlow/react-native-safe-area-context/releases/tag/v5.8.0
- the PR released in this version is fixing the build error for symbols
that were removed in RN 0.87.

- In RN 0.87's generated types, `View` is a function component, so
`React.Ref<View>` / `useRef<View>` no longer describe a host instance.
All ref sites (e.g., `Screen`, `ScreenStackItem`,
`ScreenStackHeaderConfig`) now use the public `ViewInstance` type.
- RN 0.87's real types live under the `types_generated/` (treated as
non-public) path, so any *inferred* exported type referencing them fails
`.d.ts` emit during `npm pack` (`bob build`). Fixes:
- `as HostComponent<NativeProps>` on ~30 `codegenNativeComponent`
default exports (`HostComponent` is publicly exported; other libs are
following that pattern with an explicit cast:

https://github.com/software-mansion/react-native-reanimated/blame/4.5.3/packages/react-native-reanimated/src/specs/SharedTransitionBoundaryNativeComponent.ts#L9-L12
- Nominal instance interfaces for `forwardRef` components (`export
interface ScreenInstance extends ViewInstance {}`, same for
`ScreenStackHeaderConfigInstance`) - inference stops at a nominal
interface, so the fix propagates without further annotations (was
resolving to `ReactNativeElement`, which is a non-public type from RN)
- Exported `TransitionProgressContextBody` and used it as the explicit
return type of `useTransitionProgress`.
- Set `rootDir: "./src"` in `tsconfig.build.json`
- `moduleResolution: "bundler"`, dropped `baseUrl`.** `bundler`
resolution is required to resolve RN 0.87's `exports`-based type entry
points; `baseUrl` is deprecated in TS 6 and the `paths` mappings work
relative to the config without it. For more context, see:
microsoft/TypeScript#62508
- Restored the removed `TextInputFocusEventData`. RN changed the
exported type to `TextInputFocusEvent` (now the full
`NativeSyntheticEvent`). A local backward-compat interface is
introduced.

- Migrated from `forwardRef` to React 19 ref-as-prop
- Retyped the internal ref against the native host instance
(`React.ComponentRef<typeof SearchBarNativeComponent>`) instead of the
previous double-casted `NativeSearchBar` wrapper.

- Added missing `_props` default initializers to Fabric component views
(e.g., `RNSScreenContentWrapper`). `RCTViewComponentView`'s
`updateProps:oldProps:` asserts in debug builds that every subclass
initializes `_props` with its own concrete default props in its
initializer, starting from 0.87.

- AGP 9 has built-in Kotlin support.
- AGP 9 compiles Kotlin itself by default, and additionally applying
`kotlin-android` plugin fails the build - so the plugin is now applied
only when built-in Kotlin is inactive (AGP < 9, or the consumer opted
out via `android.builtInKotlin=false`).
- Registered `src/fabric/java` in the Kotlin source set so the Fabric
sources compile under built-in Kotlin.

N/A

- `yarn check-types` - passed
- `npm pack` - passed
- codegen was verified
- `FabricExample` - built and run on iOS and Android.
- Checked the compatibility with the lowest supported RN version (0.84)

Action items yet to be covered:
- test it with SwiftPM
- full testing coverage of the most important components on (0.84, 0.87)
x (Android, iOS) x (Debug, Release) combos
- more FabricExample testing - both Debug and Release
- consider adding some commit-level check for detecting issues related
to non-public types and TS inference.

- [ ] Included code example that can be used to test this change.
- [ ] For visual changes, included screenshots / GIFs / recordings
documenting the change.
- [ ] For API changes, updated relevant public types.
- [ ] Ensured that CI passes

---------

Co-authored-by: Hur Ali <hurali97@gmail.com>
(cherry picked from commit 7708a4a)

Co-authored-by: Hur Ali <hurali97@gmail.com>
@t0maboro t0maboro added action:backport-to-v4 Add this label to any issue or PR that should be backported to the v4 line of the library. and removed action:backport-to-v4 Add this label to any issue or PR that should be backported to the v4 line of the library. labels Aug 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants